<?php

declare(strict_types=1);

namespace App\Robot\Service;

use App\Common\Robot\Gateways\Gateway;
use App\Common\Robot\Robot;
use App\CustHub\Constants\MsgTypeConstants;
use App\Enum\WordTypeEnum;
use App\Robot\Dto\LocationMessageDTO;
use App\Robot\Dto\EmojiMsgDTO;
use App\Robot\Dto\MiniProgramMessageDTO;
use App\Robot\Dto\VideoChannelMessageDTO;
use App\Robot\Dto\RobotMsgDto;
use App\Robot\Dto\VideoMessageDTO;
use Mine\Abstracts\AbstractService;
use Mine\Helper\Str;


class RobotMessageService extends AbstractService
{
    protected RobotMsgDto $data;

    protected Gateway $robotApiService;

    public function __construct(RobotMsgDto $data)
    {
        $this->data = $data;
        $this->robotApiService = make(Robot::class,[
            $this->data->getServerId(),
            $this->data->getUuid()
        ])->gateway();
    }

//    public function sendMessage()
//    {
//        $sendTimes=0;
//        $errorMessage='系统错误';
//        while ($sendTimes < 3){
//            $ret = $this->doSendMessage();
//            $errorMessage=!empty($ret['errorMessage'])?$ret['errorMessage']:$errorMessage;
//            if($ret['status']){
//                return $ret;
//            }
//            $sendTimes++;
//            //延迟重试
//            if ($sendTimes < 3) {
//                sleep(1); // 等待1秒后重试
//            }
//        }
//        return ['status'=>false,'errorMessage'=>'发送失败:'.$errorMessage,'msg_server_id'=>0];
//    }

    public function sendMessage()
    {
        logger()->info('发送参数-----'.json_encode([
            'send_time'=>datetime(time()),
            'msg_type'=>$this->data->getMsgType(),
            'content'=>$this->data->getContent(),
        ]));
        switch ($this->data->getMsgType()){
            case MsgTypeConstants::TEXT:
            case MsgTypeConstants::UNSUBSCRIBE://退订类型
                //文本
                $result = $this->sendText();
                break;
            case MsgTypeConstants::MIXED_TEXT:
                //混合文本
                $result = $this->sendMixTxtMsg();
                break;
            case MsgTypeConstants::IMAGE:
                //图片
                $result = $this->sendImage();
                break;
            case MsgTypeConstants::EMOJI:
            case MsgTypeConstants::GIF:
                //表情
                $result = $this->sendEmoji();
                break;
            case MsgTypeConstants::VIDEO:
                //视频
                $result = $this->sendVideo();
                break;
            case MsgTypeConstants::FILE:
                //文件
                $result = $this->sendFile();
                break;
            case MsgTypeConstants::URL:
            case MsgTypeConstants::QUESTIONNAIRE://问卷调查
                //链接
                $result = $this->sendUrl();
                break;
            case MsgTypeConstants::VIDEO_CHANNEL:
                //视频号
                $result = $this->sendVideoChannel();
                break;
            case MsgTypeConstants::MINI_PROGRAM:
                //小程序
                $result = $this->sendMiniProgram();
                break;
            case MsgTypeConstants::CUSTOM_MINI_PROGRAM:
                //小程序
                $result = $this->sendCustomMiniProgram();
                break;
            case MsgTypeConstants::CROWD:
                //群邀请
                $result = $this->sendCrowd();
                break;
            case MsgTypeConstants::CROWD_NOTICE:
                //群通知
                $result = $this->postGrpAnn();
                break;

            case MsgTypeConstants::PERSONAL_CARD:
            case 'business_card':
                //名片消息
                $result = $this->sendPersonalCard();
                break;
            case MsgTypeConstants::LOCATION:
                //定位消息
                $result = $this->sendLocation();
                break;
            case 'qw_video':
                $result = $this->sendQwVideo();
                break;
            default:
                logger()->info("不支持的消息类型：".$this->data->getMsgType());
                $result = [];
                break;
        }

        $msg_server_id = 0;

        if($result !== false && !empty($result['msg_server_id'])){
            $msg_server_id = $result['msg_server_id'];
        }

        $msg_unique_identifier = $result['msg_unique_identifier'] ?? '';

        logger()->info('发送结果-----'.json_encode($result).'----错误信息-----'.$this->robotApiService->getErrorMsg());
        return ['status'=>$result!=false,'msg_server_id' => $msg_server_id,'msg_unique_identifier' => $msg_unique_identifier,'errorMessage'=>$this->robotApiService->getErrorMsg()];
    }

    public function sendSpeedMessage()
    {
        logger()->info('极速群发发送参数-----'.json_encode([
                'send_time'=>datetime(time()),
                'msg_type'=>$this->data->getMsgType(),
                'content'=>$this->data->getContent(),
            ]));
        $content = $this->convertMessageData($this->data->getContent());
        logger()->info('极速群发发送参数2-----'.json_encode($content));
        if($content === false){
            return ['status'=>false,'msg_server_id' => 0,'errorMessage'=>'极速群发消息类型不支持'];
        }
        $toIdList=$this->data->getToIdList();
        //过滤不可发送人员
        $result =  $this->robotApiService->queryGroupMsgEnabledMembers($this->data->getToIdList(),$this->data->getSendType());
        logger()->info('极速群发检测可发送人员-----'.json_encode($result).'----错误信息-----'.$this->robotApiService->getErrorMsg());
        if($result === false){
            return ['status'=>false,'msg_server_id' => 0,'errorMessage'=>$this->robotApiService->getErrorMsg()];
        }
        if($this->data->getSendType()==1){
            $toIdFifthList=$result['room_id_list'];
        }else{
            $toIdFifthList=$result['user_id_list'];
        }
        logger()->info('极速群发可发送人员'.json_encode($toIdFifthList));
        logger()->info('极速群发选中发送人员'.json_encode($toIdList));
        $newToList=array_values(array_intersect($toIdList, $toIdFifthList));
        logger()->info('极速群发实际可发送人员(过滤后)'.json_encode($newToList));
        if(empty($newToList)){
            return ['status'=>false,'msg_server_id' => 0,'errorMessage'=>'检测为不可发送，请检测今日是否已经发送过了'];
        }
        $result =  $this->robotApiService->sendGroupMsg($content,$this->data->getSendType(),$newToList);
        logger()->info('极速群发发送结果-----'.json_encode($result).'----错误信息-----'.$this->robotApiService->getErrorMsg());
        $msg_server_id = 0;
        if($result !== false && !empty($result['msg_server_id'])){
            $msg_server_id = $result['msg_server_id'];
        }
        return ['status'=>$result!=false,'msg_server_id' => $msg_server_id,'errorMessage'=>$this->robotApiService->getErrorMsg(),'newToList'=>$newToList];
    }

    /**
     * 发送文本消息
     * @return array
     */
    private function sendText(): mixed
    {
        $result = $this->robotApiService->sendTextMsg($this->data->getContent(),$this->data->getToId(),$this->data->getReply());
        return $result;
    }

    /**
     * 混合文本消息
     * @return mixed
     * @throws \GuzzleHttp\Exception\GuzzleException
     */
    private function sendMixTxtMsg():mixed
    {
        $result = $this->robotApiService->sendMixTxtMsg($this->data->getContent(),$this->data->getToId(),$this->data->getReply());
        return $result;
    }

    /**
     * 发送图片消息
     * @return array
     */
    private function sendImage(): mixed
    {
        $data = container()->get(MessageDataService::class)->getImageData($this->robotApiService,$this->data->getContent(),$this->data->getToId(),$this->data->getFilename());
        if(empty($data)){
            return false;
        }
        $result = $this->robotApiService->sendImageMsg($data);
        return $result;
    }

    private function sendGif(): mixed
    {
        $data = container()->get(MessageDataService::class)->getGifData($this->robotApiService,$this->data->getContent(),$this->data->getToId(),$this->data->getFilename());
        if(empty($data)){
            return false;
        }
        $result = $this->robotApiService->sendGif($data);
        return $result;
    }

    /**
     * 发送视频消息
     * @return array
     * @throws \Psr\Container\ContainerExceptionInterface
     * @throws \Psr\Container\NotFoundExceptionInterface
     */
    private function sendVideo(): mixed
    {
        $data = container()->get(MessageDataService::class)->getVideoData($this->robotApiService,$this->data->getContent(),$this->data->getToId(),$this->data->getFilename());
        if(empty($data)){
            return false;
        }
        $result = $this->robotApiService->sendVideoMsg($data);
        return $result;
    }

    private function sendEmoji()
    {
        $data = container()->get(MessageDataService::class)->getGifData($this->robotApiService,$this->data->getContent(),$this->data->getToId(),$this->data->getFilename());
        if(empty($data)){
            return false;
        }
        $result = $this->robotApiService->sendGif($data);
        return $result;
    }

    private function sendQwVideo()
    {
        $content = $this->data->getContent();
        $filename = empty($content['file_name']) ? Str::random(12) : base64_decode($content['file_name']);
        $data = (new VideoMessageDTO())
            ->setCoverImageSize($content['cover_image_size'])
            ->setDuration($content['duration'])
            ->setFileAesKey($content['file_aeskey'])
            ->setFileId($content['file_id'])
            ->setFileSize($content['file_size'])
            ->setFileName($filename)
            ->setToId($this->data->getToId());
        $result = $this->robotApiService->sendVideoMsg($data);
        return $result;
    }

    /**
     * 发送文件消息
     * @return array
     * @throws \Psr\Container\ContainerExceptionInterface
     * @throws \Psr\Container\NotFoundExceptionInterface
     */
    private function sendFile(): mixed
    {
        $data = container()->get(MessageDataService::class)->getFileData($this->robotApiService,$this->data->getContent(),$this->data->getToId(),$this->data->getFilename());
        if(empty($data)){
            return false;
        }
        $result = $this->robotApiService->sendFileMsg($data);
        return $result;
    }

    /**
     * 发送文件消息
     * @return array
     * @throws \Psr\Container\ContainerExceptionInterface
     * @throws \Psr\Container\NotFoundExceptionInterface
     */
    private function sendUrl(): mixed
    {
        $data = container()->get(MessageDataService::class)->getUrlData($this->data->getContent(),$this->data->getToId());
        $result = $this->robotApiService->sendUrlMsg($data);
        return $result;
    }

    /**
     * 发送视频号消息
     * @return array
     */
    private function sendVideoChannel(): mixed
    {
        $content = $this->data->getContent();
        $data = (new VideoChannelMessageDTO())
            ->setEncodeData($content['encode_data'])
            ->setChannelName($content['channel_name'])
            ->setChannelUrl($content['channel_url'])
            ->setUsername($content['username'])
            ->setCoverUrl($content['cover_url'])
            ->setHeadImgUrl($content['head_img_url'])
            ->setFeedId($content['feed_id'])
            ->setFeedNo($content['feed_no'])
            ->setToId($this->data->getToId());
        $result = $this->robotApiService->sendVideoChannelMsg($data);
        return $result;
    }

    /**
     * 发送小程序消息
     * @return array
     */
    private function sendMiniProgram(): mixed
    {
        $content = $this->data->getContent();
        $appid = array_key_exists('appid', $content) ? $content['appid'] : (array_key_exists('app_id', $content) ? $content['app_id'] : '');
        $page_path = $content['pagepath'] ?? ($content['page_path'] ?? '');
        $data = (new MiniProgramMessageDTO())
            ->setTitle($content['title'] ?? '')
            ->setDesc($content['desc'] ?? '')
            ->setUsername($content['username'])
            ->setPagePath($page_path ?? '')
            ->setAppId($appid)
            ->setCoverFileAesKey($content['cover_image_aeskey'] ?? '')
            ->setCoverFileId($content['cover_image_id'] ?? '')
            ->setCoverFileSize((int)$content['cover_image_size'] ?? 0)
            ->setCoverImageMd5($content['cover_image_md5'] ?? '')
            ->setThumbUrl($content['icon_url'] ?? '')
            ->setToId($this->data->getToId());
        $result = $this->robotApiService->sendMiniProgram($data);
        return $result;
    }

    /**
     * @return mixed
     * @throws \Psr\Container\ContainerExceptionInterface
     * @throws \Psr\Container\NotFoundExceptionInterface
     */
    private function sendCustomMiniProgram():mixed
    {
        $data = container()->get(MessageDataService::class)->getCustomMiniProgramData($this->robotApiService,$this->data->getContent(),$this->data->getToId());
        if(empty($data)){
            return false;
        }
        $result = $this->robotApiService->sendMiniProgram($data);
        return $result;
    }

    /**
     * 发送群邀请
     * @return array
     */
    private function sendCrowd(): mixed
    {
        $content = $this->data->getContent();
        stdout_log()->info('发送群邀请'.$this->data->getToId());
        $result = $this->robotApiService->inviteFriendToRoom($this->data->getToId(),$content['member_list']);
        return $result;
    }

    /**
     * 发送群通知
     * @return array
     */
    private function postGrpAnn(): mixed
    {
        $result = $this->robotApiService->postGrpAnn($this->data->getToId(),$this->data->getContent());
        return $result;
    }


    private function sendPersonalCard(): mixed
    {
        $result = $this->robotApiService->sendPersonalCard($this->data->getContent(),$this->data->getToId());
        return $result;
    }

    private function sendLocation(): mixed
    {
        $content = $this->data->getContent();
        $data = (new LocationMessageDTO())
            ->setTitle($content['title'])
            ->setAddress($content['address'])
            ->setLatitude((float)$content['latitude'])
            ->setLongitude((float)$content['longitude'])
            ->setToId($this->data->getToId());
        $result = $this->robotApiService->sendLocation($data);
        return $result;
    }

    private function convertMessageData(array $messageData)
    {
        $newMessageData = [];
        foreach ($messageData as $key=>$item){
            switch ($item['msg_type']){
                case WordTypeEnum::TEXT:
                    $type=0;
                    $newMessageData[]=[
                        "msgData"=>["content"=>$item['content']],
                        "type"=>$type
                    ];
                    break;
                case WordTypeEnum::LINK:
                    $type=13;
                    $data=container()->get(MessageDataService::class)->getUrlData($item,$this->data->getToId())->toArray();
                    unset($data['to_id']);
                    $newMessageData[]=[
                        "msgData"=>$data,
                        "type"=>$type
                    ];
                    break;
                case WordTypeEnum::IMAGE:
                    $type=14;
                    $data=container()->get(MessageDataService::class)->getImageData($this->robotApiService,$item['content'],$this->data->getToId())->toArray();
                    unset($data['to_id']);
                    $newMessageData[]=[
                        "msgData"=>$data,
                        "type"=>$type
                    ];
                    break;
                case WordTypeEnum::FILE:
                    $type=15;
                    $data=container()->get(MessageDataService::class)->getFileData($this->robotApiService,$item['content'],$this->data->getToId())->toArray();
                    unset($data['to_id']);
                    $newMessageData[]=[
                        "msgData"=>$data,
                        "type"=>$type
                    ];
                    break;
                case WordTypeEnum::VIDEO:
                    $type=23;
                    $data=container()->get(MessageDataService::class)->getFileData($this->robotApiService,$item['content'],$this->data->getToId())->toArray();
                    unset($data['to_id']);
                    $newMessageData[]=[
                        "msgData"=>$data,
                        "type"=>$type
                    ];
                    break;
                case WordTypeEnum::MINI_PROGRAM:
                    $type=78;
                    $newMessageData[]=[
                        "msgData"=>$item['content'],
                        "type"=>$type
                    ];
                    break;
                case WordTypeEnum::CUSTOM_MINI_PROGRAM:
                    $type=78;
                    $data=container()->get(MessageDataService::class)->getCustomMiniProgramData($this->robotApiService,$item['content'],$this->data->getToId())->toArray();
                    unset($data['to_id']);
                    $newMessageData[]=[
                        "msgData"=>$data,
                        "type"=>$type
                    ];
                    break;
                case WordTypeEnum::VIDEO_CHANNEL:
//                    $type=78;
//                    $newMessageData[]=[
//                        "msgData"=>$item['content'],
//                        "type"=>$type
//                    ];
                    break;
                default:
                    return false;
            }
        }
        return $newMessageData;
    }
}